package com.hqd.share;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Demo {

    private static List<Person> getData() {
        return Stream
                .generate(() -> new Person("TestUser" + new Random().nextInt(100), new Random().nextInt(100), new Random().nextBoolean()))
                .limit(20)
                .collect(Collectors.toList());
    }

    private static void printData(List<Person> list) {
        list.forEach(v -> {
            System.out.println(v.toString());
        });
    }

    private static void list2Map(List<Person> list) {
        // 方式1：单纯转换-k,v都为对象的属性
        System.out.println("============MAP1===============");
        Map<String, Integer> map1 = list
                .stream()
                .collect(Collectors.toMap(Person::getName, Person::getAge, (k1, k2) -> k2));
        map1.forEach((k, v) -> {
            System.out.println(k);
            System.out.println(v);
        });

        // 方式2：单纯转换-k为对象属性，v是对象本身
        System.out.println("============MAP2===============");
        Map<String, Person> map2 = list
                .stream()
                .collect(Collectors.toMap(Person::getName, Function.identity(), (k1, k2) -> k2));
        map2.forEach((k, v) -> {
            System.out.println(k);
            System.out.println(v.toString());
        });

        // 方式3：分组
        // Grouping的Key如果是Null会空指针异常
        System.out.println("============MAP3===============");
        Map<Boolean, List<Person>> map3 = list
                .stream()
                .collect(Collectors.groupingBy(Person::isSex));
        map3.forEach((k, v) -> {
            System.out.println(k);
            v.stream().forEach(System.out::println);
            System.out.println();
            System.out.println();
        });

        // 方式4：分组(解决空指针可能性)
        System.out.println("============MAP4===============");
        Map<Boolean, List<Person>> map4 = list
                .stream()
                .collect(Collectors.groupingBy(k -> Optional.ofNullable(k.isSex()).orElse(Boolean.FALSE)));
        map4.forEach((k, v) -> {
            System.out.println(k);
            v.stream().forEach(System.out::println);
            System.out.println();
            System.out.println();
        });

        // 方式5：多级分组
        System.out.println("============MAP5===============");
        Map<Boolean, Map<Integer, List<Person>>> map5 = list
                .stream()
                .collect(Collectors.groupingBy(k -> Optional.ofNullable(k.isSex()).orElse(Boolean.FALSE),
                        Collectors.groupingBy(Person::getAge)));

        // 方式6：根据条件分组(也可以多层级分组)
        System.out.println("============MAP5===============");
        Map<Boolean, List<Person>> map6 = list
                .stream()
                .collect(Collectors.partitioningBy(v -> v.getAge() > 20));

    }

    private static void mdMap(List<Person> list) {
        // 每个人的年龄减100

        // 返回值为List<Integer>
        list
                .stream()
                .map(v -> v.getAge() - 100)
                .forEach(System.out::println);

        // 返回值为List<Person>
        list
                .stream()
                .map(v -> {
                    v.setAge(v.getAge() - 100);
                    return v;
                })
                .forEach(System.out::println);

        // 返回值为List<Map>
        list
                .stream()
                .map(v -> {
                    return Map.ofEntries(
                            Map.entry("name", v.getName()),
                            Map.entry("age", v.getAge()),
                            Map.entry("sex", v.isSex())
                    );
                })
                .forEach(System.out::println);
    }

    private static void mdFilter(List<Person> list) {
        // 找到年龄大于18的性别为True的元素
        list
                .stream()
                .filter(v -> v.getAge() > 18)
                .filter(v -> v.isSex())
                .forEach(System.out::println);
    }

    private static void mdFindAndMatch(List<Person> list) {
        // 匹配第一个性别是True的
        Person p = list
                .stream()
                .filter(v -> v.isSex())
                .findFirst()
                .orElse(null);
        System.out.println(p.toString());

        // 匹配随便一个
        p = list
                .stream()
                .findAny()
                .orElse(new Person());
        System.out.println(p);

        // 只要有一个元素符合就返回True
        boolean hasRs = list
                .stream()
                .anyMatch(v -> v.getAge() > 50);

        // 所有元素全部符合才返回True
        hasRs = list
                .stream()
                .allMatch(v -> v.getAge() > 50);

        hasRs = list
                .stream()
                .noneMatch(v -> v.getAge() > 50);

    }

    private static void mdReducec(List<Person> list) {
        // 获取所有人年龄的和
        int ageSum = list
                .stream()
                .map(Person::getAge)
                .reduce(0, (a, b) -> a + b);
        System.out.println(ageSum);
    }

    private static void mdSort(List<Person> list) {
        // 按照年纪排序 ASC
        list
                .stream()
                .sorted(Comparator.comparing(Person::getAge))
                .forEach(System.out::println);

        // DESC,如果排序字段为Null，放在最前面，放在最后用【nullLast()】
        list
                .stream()
                .sorted(Comparator.comparing(Person::getAge, Comparator.nullsFirst(Integer::compare)).reversed())
                .forEach(System.out::println);


        Stream
                .generate(() -> new Random().nextInt(100))
                .limit(10)
                .sorted((x, y) -> x - y)
                .forEach(System.out::println);
    }

    private static void mdMaxMin(List<Person> list) {
        // 获取年纪最大的
        Person person = list
                .stream()
                .max(Comparator.comparing(Person::getAge))
                .orElse(new Person());
        System.out.println(person.toString());

        int maxNum = Stream
                .generate(() -> new Random().nextInt(100))
                .limit(10)
                .map(v -> {
                    System.out.println(v);
                    return v;
                })
                .max((x, y) -> x - y)
                .orElse(0);
        System.out.println("最大数：" + maxNum);

        // min同max
    }


    private static void mdOther() {
        // 去重
        List<Integer> iList = Arrays.asList(1, 2, 3, 4, 1, 2, 3, 4);
        iList.stream().distinct().forEach(System.out::println);

        // 截取:从第一个到第N个
        List<String> sList = Stream
                .generate(() -> "Hello")
                .limit(10)
                .collect(Collectors.toList());
        sList.forEach(System.out::println);

        // 跳过前N个
        sList
                .stream()
                .skip(5)
                .forEach(System.out::println);
    }

    private static void mdOptional(List<Person> list) {
        Map<Boolean, Map<Integer, List<Person>>> map = list
                .stream()
                .collect(Collectors.groupingBy(k -> Optional.ofNullable(k.isSex()).orElse(Boolean.FALSE),
                        Collectors.groupingBy(Person::getAge)));

        // 取得并打印map中，key为true的年纪是20的List<Person>的第二个，传统代码
        if (null != map && null != map.get(Boolean.TRUE)) {
            Map<Integer, List<Person>> innerMap = map.get(Boolean.TRUE);
            if (null != innerMap && null != innerMap.get(20)) {
                List<Person> plist = innerMap.get(20);
                if (null != plist && plist.size()>2) {
                    Person p = plist.get(1);
                    System.out.println(p.toString());
                } else {
                    System.out.println(new Person().toString());
                }
            }
        }

        // 使用Optional
        Person p = Optional.ofNullable(map)
                .map(v -> v.get(Boolean.TRUE))
                .map(v -> v.get(20))
                .map(v -> v.get(1))
                .orElse(new Person());
        System.out.println(p.toString());

        if (Optional.ofNullable(p).isEmpty()) {
            // do something
            // 等同于 if (null == p)
        }

        if (Optional.ofNullable(p).isPresent()) {
            // do something
            // 等同于 if (null != p)
        }

        //String s = "abc";
        String s = null;

        // 在不能明确 s 是否为空的时候
        System.out.println(Optional.ofNullable(s).orElse("default"));

        // 使用of时，如果参数为null，会抛出NullPorint
        //Optional o = Optional.of(s);

        // 取得Optional里的值
        System.out.println(Optional.ofNullable(s).get());
    }
    public static void main(String[] args) {
    	
    	// 在Lambda中使用外部变量时注意事项：
    	// 使用的变量必须是Final的
    	// 这个Final不说定义类型的Fianl
    	// 而是Lambda中的变量不能改变，即使是在外面改变也不行。

        List<Person> list = getData();

        //printData(list);
        //list2Map(list);
        //mdMap(list);
        //mdFilter(list);
        //mdReducec(list);
        //mdSort(list);
        //mdMaxMin(list);
        //mdOther();

        mdOptional(list);
    }

}
